package com.om.switchtopolymorphism;

public class RateCalculator {
	double calculateRate(Customer customer) {
		switch (customer.customerType) {
		case consumer:
			return calculateConsumerRate(customer);
		case business:
			return calculateBusinessRate(customer);
		case industrial:
			return calculateIndustrialRate(customer);
		default:
			return 0;
		}
	}

	double calculateConsumerRate(Customer customer) {
		if (customerIsEligibleForLifelineRate(customer)) {
			return calculateLifelineRate(customer);
		}

		return calculateTerritorialRate(customer);
	}

	boolean customerIsEligibleForLifelineRate(Customer customer) {
		return customer.rate == Customer.LIFELINE && customer.kwh <= 200;
	}

	double calculateLifelineRate(Customer customer) {
		int tier2Kwh = Math.max(customer.kwh - 100, 0);
		int tier1Kwh = customer.kwh - tier2Kwh;
		return tier1Kwh * 0.03 + tier2Kwh * 0.05;
	}

	double calculateTerritorialRate(Customer customer) {
		switch (calculateTerritory(customer.address)) {
		case 1:
			// spec says territory 1 and 2 use same rate.
		case 2:
			return customer.kwh * (isWinter() ? .07 : .06);
		case 3:
			return customer.kwh * .065;
		default:
			return 0;
		}
	}

	int calculateTerritory(int address) {
		return address;
	}

	boolean isWinter() {
		return false;
	}

	double calculateBusinessRate(Customer customer) {
		double rate = 0;

		for (Site site : customer.sites) {
			rate += calculateSlidingScale(site.kwh);
		}

		return rate;
	}

	int calculateSlidingScale(int kwh) {
		return kwh;
	}

	double calculateIndustrialRate(Customer customer) {
		double businessRate = calculateBusinessRate(customer);
		double industrialRateModifier = calculateIndustrialRateModifier(customer);
		return businessRate * industrialRateModifier;
	}

	double calculateIndustrialRateModifier(Customer customer) {
		switch (customer.industrialRate) {
		case interruptable:
			return .8;
		case oneHourNotice:
			return .9;
		default:
			return .95;
		}
	}

}
